package com.xframe.xdal.core.util.redis.command;

import com.alibaba.fastjson.JSON;
import com.xframe.xdal.core.model.IModel;
import com.xframe.xdal.core.util.StringUtil;
import com.xframe.xdal.core.util.redis.pool.IRedisPool;
import redis.clients.jedis.BitOP;
import redis.clients.jedis.commands.JedisCommands;
import redis.clients.jedis.commands.MultiKeyCommands;
import redis.clients.jedis.params.SetParams;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class SetCommand {


    private IRedisPool pool = null;


    public SetCommand(IRedisPool pool){
        this.pool = pool;
    }
    /**
     * 添加一个指定类型的对象
     *
     * @param key   key
     * @param value 值
     * @return 成功返回1, 失败返回0
     */
    public int set(String key, String value, SetParams setParams) {
        if (StringUtil.isValueNull(key, value)) {
            return 0;
        }
        JedisCommands client = null;
        try {
            client = pool.getClient();
            if (client.set(key, value, setParams).equalsIgnoreCase("ok")) {
                return 1;
            } else {
                return 0;
            }
        } finally {
            pool.close(client);
        }
    }

    /**
     * 添加一个指定类型的对象 过期时长
     * @param key   key
     * @param value 值
     * @param second 生存时间 秒为单位
     * @return 成功返回1, 失败返回0
     */
    public int set(String key, String value, int second) {
        if (StringUtil.isValueNull(key, value)) {
            return 0;
        }
        if(second <= 0){
            return 0;
        }
        return set(key,value,SetParams.setParams().ex(second));
    }

    /**
     * 添加一个指定类型的对象 不可覆盖 (过期时长)
     * @param key   key
     * @param value 值
     * @return
     */
    public int setNx(String key, String value) {

        if (StringUtil.isValueNull(key, value)) {
            return 0;
        }
        JedisCommands client = null;
        try {
            client = pool.getClient();
            if (client.setnx(key, value) == 1L) {
                return 1;
            } else {
                return 0;
            }
        } finally {
            pool.close(client);
        }




    }



    /**
     * 添加一个指定类型的对象
     *
     * @param key   key
     * @param value 值
     * @return 成功返回1, 失败返回0
     */
    public int set(String key, String value) {
        if (StringUtil.isValueNull(key, value)) {
            return 0;
        }
        JedisCommands client = null;
        try {
            client = pool.getClient();
            if (client.set(key, value).equalsIgnoreCase("ok")) {
                return 1;
            } else {
                return 0;
            }
        } finally {
            pool.close(client);
        }
    }

    /**
     * 用 value 参数覆写(overwrite)给定 key 所储存的字符串值，从偏移量 offset 开始。
     * @param key   key
     * @param value  值
     * @param offset  偏移量
     * @return 成功返回1, 失败返回0
     */
    public int setBit(String key, String value, long offset) {
        if (StringUtil.isValueNull(key, value, offset)) {
            return 0;
        }
       JedisCommands client = null;
        try {
            client = pool.getClient();
            if (client.setbit(key,offset, value)) {
                return 1;
            } else {
                return 0;
            }
        } finally {
            pool.close(client);
        }
    }

    /**
     * 返回 key 所储存的字符串值的长度。
     * @param key   key
     * @return 返回字符串长度
     */
    public int strlen(String key) {
        if (StringUtil.isValueNull(key)) {
            return 0;
        }
       JedisCommands client = null;
        try {
            client = pool.getClient();
            return client.strlen(key).intValue();
        } finally {
            pool.close(client);
        }
    }

    /**
     * 添加一个指定类型的对象 并设置有效期（毫秒）
     * @param key   key
     * @param value 值
     * @param second 生存时间 毫秒秒为单位
     * @return 成功返回1, 失败返回0
     */
    public int setPx(String key,String value,int second) {
        if (StringUtil.isValueNull(key, value)) {
            return 0;
        }
        return set(key,value,SetParams.setParams().px(second));
    }

    /**
     * 添加一个指定类型的对象 并设置有效期（毫秒）
     * @param key   key
     * @param value 值
     * @param second 生存时间 秒秒为单位
     * @return 成功返回1, 失败返回0
     */
    public int setEx(String key,String value,int second) {
        if (StringUtil.isValueNull(key, value)) {
            return 0;
        }
        return set(key,value,SetParams.setParams().ex(second));
    }


    /**
     * 同时设置一个或多个 key-value 对
     * @param key   key
     * @param map   key-value 值
     * @return 成功返回1, 失败返回0
     */
    public int mset(String key, Map<String, String> map) {
        if (StringUtil.isValueNull(key, map)) {
            return 0;
        }
       JedisCommands client = null;
        try {
            client = pool.getClient();
            if (client.hmset(key, map).equalsIgnoreCase("ok")) {
                return 1;
            } else {
                return 0;
            }
        } finally {
            pool.close(client);
        }
    }

    /**
     * 用 value 参数覆写(overwrite)给定 key 所储存的字符串值，从偏移量 offset 开始。
     * @param key   key
     * @param value  值
     * @param offset  偏移量
     * @return 返回字符串长度
     */
    public Long setRange(String key,String value,long offset) {
        if (StringUtil.isValueNull(key, value, offset)) {
            return 0L;
        }
       JedisCommands client = null;
        try {
           client = pool.getClient();
           return client.setrange(key, offset ,value);
        } finally {
            pool.close(client);
        }
    }

    /**
     * 为 key 中所储存的值加上浮点数增量 increment
     * @param key   key
     * @param increment  上浮点数
     * @return 返回上浮后的结果
     */
    public Double incrByFloat(String key,double increment) {
        if (StringUtil.isValueNull(key, increment)) {
            return 0D;
        }
       JedisCommands client = null;
        try {
            client = pool.getClient();
            return client.incrByFloat(key,increment);
        } finally {
            pool.close(client);
        }
    }

    /**
     * 将 key 所储存的值加上增量 increment
     * @param key   key
     * @param increment  上浮数
     * @return 返回上浮后的结果
     */
    public Long incrBy(String key,long increment) {
        if (StringUtil.isValueNull(key, increment)) {
            return 0L;
        }
       JedisCommands client = null;
        try {
            client = pool.getClient();
            return client.incrBy(key,increment);
        } finally {
            pool.close(client);
        }
    }

    /**
     * 将 key 所储存的值减去减量 decrement
     * @param key   key
     * @param increment  减去数
     * @return 返回减去数后的结果
     */
    public Long decrBy(String key,long increment) {
        if (StringUtil.isValueNull(key, increment)) {
            return 0L;
        }
       JedisCommands client = null;
        try {
            client = pool.getClient();
            return client.decrBy(key,increment);
        } finally {
            pool.close(client);
        }
    }

    /**
     * 将 key 中储存的数字值增一
     * @param key   key
     * @return 返回上浮后的结果
     */
    public Long incr(String key) {
        if (StringUtil.isValueNull(key)) {
            return 0L;
        }
       JedisCommands client = null;
        try {
            client = pool.getClient();
            return client.incr(key);
        } finally {
            pool.close(client);
        }
    }

    /**
     * 将 key 中储存的数字值减一
     * @param key   key
     * @return 返回减一后的结果
     */
    public Long decr(String key) {
        if (StringUtil.isValueNull(key)) {
            return 0L;
        }
       JedisCommands client = null;
        try {
            client = pool.getClient();
            return client.decr(key);
        } finally {
            pool.close(client);
        }
    }

    /**
     * 计算给定字符串中，被设置为 1 的比特位的数量
     * @param key    key
     * @param start  开始数值
     * @param end    结束数值
     * @return 比特位的数量
     */
    public Long bitCount(String key, long start, long end) {
        if (StringUtil.isValueNull(key)) {
            return 0L;
        }
       JedisCommands client = null;
        try {
            client = pool.getClient();
            return client.bitcount(key,start,end);
        } finally {
            pool.close(client);
        }
    }

    /**
     * 如果 key 已经存在并且是一个字符串， APPEND 命令将 value 追加到 key 原来的值的末尾
     * @param key
     * @param value
     * @return 返回执行结果后的value长度
     */
    public Long appEnd(String key, String value) {
        if (StringUtil.isValueNull(key)) {
            return 0L;
        }
       JedisCommands client = null;
        try {
            client = pool.getClient();
            return client.append(key, value);
        } finally {
            pool.close(client);
        }
    }

    /**
     * 对一个或多个保存二进制位的字符串 key 进行位元操作，并将结果保存到 destkey 上
     * @param op   operation 可以是 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种：
     * @param destKey  新key
     * @param srcKeys  合并的key
     * @return 保存到 destkey 的字符串的长度，和输入 key 中最长的字符串长度相等。
     */
    public Long bitOp(BitOP op, String destKey, String... srcKeys){
        if (StringUtil.isValueNull(op,destKey,srcKeys)) {
            return -1L;
        }
        MultiKeyCommands client = null;
        try {
            client = pool.getMultiKeyCommands();
            return client.bitop(op,destKey,srcKeys);
        } finally {
            pool.close(client);
        }
    }

    /**
     * 将list对象放入redis
     * @param key
     * @param list  list对象
     * @return 成功返回1, 失败返回0
     * @param <T>
     */
    public <T extends IModel> int setCollection(String key, Collection<T> list){
        if (StringUtil.isValueNull(key,list)) {
            return 0;
        }
        Map<String,String> data = new HashMap<>();
        for(IModel model : list){
            String mapKey = model.getObjectId().toString();
            String json = JSON.toJSONString(model);
            data.put(mapKey,json);
        }
        String json = JSON.toJSONString(data);
        return set(key,json);
    }

    /**
     *  将对象放入redis
     * @param key
     * @param value
     * @return  成功返回1, 失败返回0
     * @param <T>
     */
    public <T> int setObject(String key, T value){
        if (StringUtil.isValueNull(key,value)) {
            return 0;
        }
        String json = JSON.toJSONString(value);
        return set(key,json);
    }


    /**
     *  将对象放入redis
     * @param key
     * @param value
     * @return  成功返回1, 失败返回0
     * @param <T>
     */
    public <T> int setObject(String key, T value,int second){
        if (StringUtil.isValueNull(key,value)) {
            return 0;
        }
        String json = JSON.toJSONString(value);
        return setEx(key,json,second);
    }

}
